; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -march=amdgcn -mcpu=bonaire -stop-after=amdgpu-remove-incompatible-functions < %s 2>%t | FileCheck -check-prefixes=GFX7,IR %s
; RUN: FileCheck --check-prefix=WARN-GFX7 %s < %t
; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s

; RUN: llc -march=amdgcn -mcpu=fiji -stop-after=amdgpu-remove-incompatible-functions < %s 2>%t | FileCheck -check-prefixes=GFX8,IR %s
; RUN: FileCheck --check-prefix=WARN-GFX8 %s < %t
; RUN: llc -march=amdgcn -mcpu=fiji -verify-machineinstrs < %s

; RUN: llc -march=amdgcn -mcpu=gfx906 -stop-after=amdgpu-remove-incompatible-functions < %s 2>%t | FileCheck -check-prefixes=GFX9,GFX906,IR %s
; RUN: FileCheck --check-prefix=WARN-GFX906 %s < %t
; RUN: llc -march=amdgcn -mcpu=gfx906 -verify-machineinstrs < %s

; RUN: llc -march=amdgcn -mcpu=gfx90a -stop-after=amdgpu-remove-incompatible-functions < %s 2>%t | FileCheck -check-prefixes=GFX9,GFX90A,IR %s
; RUN: FileCheck --check-prefix=WARN-GFX90A %s < %t
; RUN: llc -march=amdgcn -mcpu=gfx90a -verify-machineinstrs < %s

; RUN: llc -march=amdgcn -mcpu=gfx1011 -stop-after=amdgpu-remove-incompatible-functions < %s 2>%t | FileCheck -check-prefixes=GFX10,IR %s
; RUN: FileCheck --check-prefix=WARN-GFX10 %s < %t
; RUN: llc -march=amdgcn -mcpu=gfx1011 -verify-machineinstrs < %s

; RUN: llc -march=amdgcn -mcpu=gfx1100 -stop-after=amdgpu-remove-incompatible-functions < %s 2>%t | FileCheck -check-prefixes=GFX11,IR %s
; RUN: FileCheck --check-prefix=WARN-GFX11 %s < %t
; RUN: llc -march=amdgcn -mcpu=gfx1100 -verify-machineinstrs < %s

; Note: This test checks the IR, but also has a run line to codegen the file just to check we
; do not crash when trying to select those functions.

; WARN-GFX7: needs_dpp: removing function: +dpp is not supported on the current target
; WARN-GFX7: needs_16bit_insts: removing function: +16-bit-insts is not supported on the current target
; WARN-GFX7: needs_gfx8_insts: removing function: +gfx8-insts is not supported on the current target
; WARN-GFX7: needs_gfx9_insts: removing function: +gfx9-insts is not supported on the current target
; WARN-GFX7: needs_gfx10_insts: removing function: +gfx10-insts is not supported on the current target
; WARN-GFX7: needs_gfx11_insts: removing function: +gfx11-insts is not supported on the current target
; WARN-GFX7: needs_dot1_insts: removing function: +dot1-insts is not supported on the current target
; WARN-GFX7: needs_dot2_insts: removing function: +dot2-insts is not supported on the current target
; WARN-GFX7: needs_dot3_insts: removing function: +dot3-insts is not supported on the current target
; WARN-GFX7: needs_dot4_insts: removing function: +dot4-insts is not supported on the current target
; WARN-GFX7: needs_dot5_insts: removing function: +dot5-insts is not supported on the current target
; WARN-GFX7: needs_dot6_insts: removing function: +dot6-insts is not supported on the current target
; WARN-GFX7: needs_dot7_insts: removing function: +dot7-insts is not supported on the current target
; WARN-GFX7: needs_dot8_insts: removing function: +dot8-insts is not supported on the current target
; WARN-GFX7-NOT: not supported

; WARN-GFX8: needs_gfx9_insts: removing function: +gfx9-insts is not supported on the current target
; WARN-GFX8: needs_gfx10_insts: removing function: +gfx10-insts is not supported on the current target
; WARN-GFX8: needs_gfx11_insts: removing function: +gfx11-insts is not supported on the current target
; WARN-GFX8: needs_dot1_insts: removing function: +dot1-insts is not supported on the current target
; WARN-GFX8: needs_dot2_insts: removing function: +dot2-insts is not supported on the current target
; WARN-GFX8: needs_dot3_insts: removing function: +dot3-insts is not supported on the current target
; WARN-GFX8: needs_dot4_insts: removing function: +dot4-insts is not supported on the current target
; WARN-GFX8: needs_dot5_insts: removing function: +dot5-insts is not supported on the current target
; WARN-GFX8: needs_dot6_insts: removing function: +dot6-insts is not supported on the current target
; WARN-GFX8: needs_dot7_insts: removing function: +dot7-insts is not supported on the current target
; WARN-GFX8: needs_dot8_insts: removing function: +dot8-insts is not supported on the current target
; WARN-GFX8-NOT: not supported

; WARN-GFX906: needs_gfx10_insts: removing function: +gfx10-insts is not supported on the current target
; WARN-GFX906: needs_gfx11_insts: removing function: +gfx11-insts is not supported on the current target
; WARN-GFX906: needs_dot3_insts: removing function: +dot3-insts is not supported on the current target
; WARN-GFX906: needs_dot4_insts: removing function: +dot4-insts is not supported on the current target
; WARN-GFX906: needs_dot5_insts: removing function: +dot5-insts is not supported on the current target
; WARN-GFX906: needs_dot6_insts: removing function: +dot6-insts is not supported on the current target
; WARN-GFX906: needs_dot8_insts: removing function: +dot8-insts is not supported on the current target
; WARN-GFX906-NOT: not supported

; WARN-GFX90A: needs_gfx10_insts: removing function: +gfx10-insts is not supported on the current target
; WARN-GFX90A: needs_gfx11_insts: removing function: +gfx11-insts is not supported on the current target
; WARN-GFX90A: needs_dot8_insts: removing function: +dot8-insts is not supported on the current target
; WARN-GFX90A-NOT: not supported

; WARN-GFX10: needs_gfx11_insts: removing function: +gfx11-insts is not supported on the current target
; WARN-GFX10: needs_dot3_insts: removing function: +dot3-insts is not supported on the current target
; WARN-GFX10: needs_dot4_insts: removing function: +dot4-insts is not supported on the current target
; WARN-GFX10: needs_dot8_insts: removing function: +dot8-insts is not supported on the current target
; WARN-GFX10-NOT: not supported

; WARN-GFX11: needs_dot1_insts: removing function: +dot1-insts is not supported on the current target
; WARN-GFX11: needs_dot2_insts: removing function: +dot2-insts is not supported on the current target
; WARN-GFX11: needs_dot3_insts: removing function: +dot3-insts is not supported on the current target
; WARN-GFX11: needs_dot4_insts: removing function: +dot4-insts is not supported on the current target
; WARN-GFX11: needs_dot6_insts: removing function: +dot6-insts is not supported on the current target
; WARN-GFX11-NOT: not supported

; GFX7:   @GVRefs {{.*}} zeroinitializer
; GFX8:   @GVRefs {{.*}} [ptr @needs_dpp, ptr @needs_16bit_insts, ptr @needs_gfx8_insts, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null, ptr null] 
; GFX906: @GVRefs {{.*}} [ptr @needs_dpp, ptr @needs_16bit_insts, ptr @needs_gfx8_insts, ptr @needs_gfx9_insts, ptr null, ptr null, ptr @needs_dot1_insts, ptr @needs_dot2_insts, ptr null, ptr null, ptr null, ptr null, ptr @needs_dot7_insts, ptr null]
; GFX90A: @GVRefs {{.*}} [ptr @needs_dpp, ptr @needs_16bit_insts, ptr @needs_gfx8_insts, ptr @needs_gfx9_insts, ptr null, ptr null, ptr @needs_dot1_insts, ptr @needs_dot2_insts, ptr @needs_dot3_insts, ptr @needs_dot4_insts, ptr @needs_dot5_insts, ptr @needs_dot6_insts, ptr @needs_dot7_insts, ptr null]
; GFX10:  @GVRefs {{.*}} [ptr @needs_dpp, ptr @needs_16bit_insts, ptr @needs_gfx8_insts, ptr @needs_gfx9_insts, ptr @needs_gfx10_insts, ptr null, ptr @needs_dot1_insts, ptr @needs_dot2_insts, ptr null, ptr null, ptr @needs_dot5_insts, ptr @needs_dot6_insts, ptr @needs_dot7_insts, ptr null]
; GFX11:  @GVRefs {{.*}} [ptr @needs_dpp, ptr @needs_16bit_insts, ptr @needs_gfx8_insts, ptr @needs_gfx9_insts, ptr @needs_gfx10_insts, ptr @needs_gfx11_insts, ptr null, ptr null, ptr null, ptr null, ptr @needs_dot5_insts, ptr null, ptr @needs_dot7_insts, ptr @needs_dot8_insts]
@GVRefs = internal global [14 x ptr] [
  ptr @needs_dpp,
  ptr @needs_16bit_insts,
  ptr @needs_gfx8_insts,
  ptr @needs_gfx9_insts,
  ptr @needs_gfx10_insts,
  ptr @needs_gfx11_insts,
  ptr @needs_dot1_insts,
  ptr @needs_dot2_insts,
  ptr @needs_dot3_insts,
  ptr @needs_dot4_insts,
  ptr @needs_dot5_insts,
  ptr @needs_dot6_insts,
  ptr @needs_dot7_insts,
  ptr @needs_dot8_insts
]

; GFX7: @ConstantExpr = internal global i64 0
@ConstantExpr = internal global i64 ptrtoint (ptr @needs_dpp to i64)

define void @needs_dpp(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #0 {
; GFX7-NOT:   define void @needs_dpp(
; GFX8:       define void @needs_dpp(
; GFX9:       define void @needs_dpp(
; GFX10:      define void @needs_dpp(
; GFX11:      define void @needs_dpp(
entry:
  %cmp = icmp eq i64 %a, 0
  br i1 %cmp, label %if, label %else

if:
  %ld = load i64, ptr %in
  br label %endif

else:
  %add = add i64 %a, %b
  br label %endif

endif:
  %phi = phi i64 [%ld, %if], [%add, %else]
  store i64 %phi, ptr %out
  ret void
}

define void @needs_16bit_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #1 {
; GFX7-NOT:   define void @needs_16bit_insts(
; GFX8:       define void @needs_16bit_insts(
; GFX9:       define void @needs_16bit_insts(
; GFX10:      define void @needs_16bit_insts(
; GFX11:      define void @needs_16bit_insts(
entry:
  %cmp = icmp eq i64 %a, 0
  br i1 %cmp, label %if, label %else

if:
  %ld = load i64, ptr %in
  br label %endif

else:
  %add = add i64 %a, %b
  br label %endif

endif:
  %phi = phi i64 [%ld, %if], [%add, %else]
  store i64 %phi, ptr %out
  ret void
}

define void @needs_gfx8_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #2 {
; GFX7-NOT:   define void @needs_gfx8_insts(
; GFX8:       define void @needs_gfx8_insts(
; GFX9:       define void @needs_gfx8_insts(
; GFX10:      define void @needs_gfx8_insts(
; GFX11:      define void @needs_gfx8_insts(
entry:
  %cmp = icmp eq i64 %a, 0
  br i1 %cmp, label %if, label %else

if:
  %ld = load i64, ptr %in
  br label %endif

else:
  %add = add i64 %a, %b
  br label %endif

endif:
  %phi = phi i64 [%ld, %if], [%add, %else]
  store i64 %phi, ptr %out
  ret void
}

define void @needs_gfx9_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #3 {
; GFX7-NOT:   define void @needs_gfx9_insts(
; GFX8-NOT:   define void @needs_gfx9_insts(
; GFX9:       define void @needs_gfx9_insts(
; GFX10:      define void @needs_gfx9_insts(
; GFX11:      define void @needs_gfx9_insts(
entry:
  %cmp = icmp eq i64 %a, 0
  br i1 %cmp, label %if, label %else

if:
  %ld = load i64, ptr %in
  br label %endif

else:
  %add = add i64 %a, %b
  br label %endif

endif:
  %phi = phi i64 [%ld, %if], [%add, %else]
  store i64 %phi, ptr %out
  ret void
}

define void @needs_gfx10_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #4 {
; GFX7-NOT:   define void @needs_gfx10_insts(
; GFX8-NOT:   define void @needs_gfx10_insts(
; GFX9-NOT:   define void @needs_gfx10_insts(
; GFX10:      define void @needs_gfx10_insts(
; GFX11:      define void @needs_gfx10_insts(
entry:
  %cmp = icmp eq i64 %a, 0
  br i1 %cmp, label %if, label %else

if:
  %ld = load i64, ptr %in
  br label %endif

else:
  %add = add i64 %a, %b
  br label %endif

endif:
  %phi = phi i64 [%ld, %if], [%add, %else]
  store i64 %phi, ptr %out
  ret void
}

define void @needs_gfx11_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #5 {
; GFX7-NOT:   define void @needs_gfx11_insts(
; GFX8-NOT:   define void @needs_gfx11_insts(
; GFX9-NOT:   define void @needs_gfx11_insts(
; GFX10-NOT:  define void @needs_gfx11_insts(
; GFX11:      define void @needs_gfx11_insts(
entry:
  %cmp = icmp eq i64 %a, 0
  br i1 %cmp, label %if, label %else

if:
  %ld = load i64, ptr %in
  br label %endif

else:
  %add = add i64 %a, %b
  br label %endif

endif:
  %phi = phi i64 [%ld, %if], [%add, %else]
  store i64 %phi, ptr %out
  ret void
}

define void @needs_dot1_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #6 {
; GFX7-NOT:     define void @needs_dot1_insts(
; GFX8-NOT:     define void @needs_dot1_insts(
; GFX9:         define void @needs_dot1_insts(
; GFX10:        define void @needs_dot1_insts(
; GFX11-NOT:    define void @needs_dot1_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}

define void @needs_dot2_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #7 {
; GFX7-NOT:     define void @needs_dot2_insts(
; GFX8-NOT:     define void @needs_dot2_insts(
; GFX9:         define void @needs_dot2_insts(
; GFX10:        define void @needs_dot2_insts(
; GFX11-NOT:    define void @needs_dot2_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}

define void @needs_dot3_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #8 {
; GFX7-NOT:   define void @needs_dot3_insts(
; GFX8-NOT:   define void @needs_dot3_insts(
; GFX906-NOT: define void @needs_dot3_insts(
; GFX90A:     define void @needs_dot3_insts(
; GFX10-NOT:  define void @needs_dot3_insts(
; GFX11-NOT:  define void @needs_dot3_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}


define void @needs_dot4_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #9 {
; GFX7-NOT:   define void @needs_dot4_insts(
; GFX8-NOT:   define void @needs_dot4_insts(
; GFX906-NOT: define void @needs_dot4_insts(
; GFX90A:     define void @needs_dot4_insts(
; GFX10-NOT:  define void @needs_dot4_insts(
; GFX11-NOT:  define void @needs_dot4_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}

define void @needs_dot5_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #10 {
; GFX7-NOT:   define void @needs_dot5_insts(
; GFX8-NOT:   define void @needs_dot5_insts(
; GFX906-NOT: define void @needs_dot5_insts(
; GFX90A:     define void @needs_dot5_insts(
; GFX10:      define void @needs_dot5_insts(
; GFX11:      define void @needs_dot5_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}

define void @needs_dot6_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #11 {
; GFX7-NOT:   define void @needs_dot6_insts(
; GFX8-NOT:   define void @needs_dot6_insts(
; GFX906-NOT: define void @needs_dot6_insts(
; GFX90A:     define void @needs_dot6_insts(
; GFX10:      define void @needs_dot6_insts(
; GFX11-NOT:  define void @needs_dot6_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}

define void @needs_dot7_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #12 {
; GFX7-NOT:   define void @needs_dot7_insts(
; GFX8-NOT:   define void @needs_dot7_insts(
; GFX9:       define void @needs_dot7_insts(
; GFX10:      define void @needs_dot7_insts(
; GFX11:      define void @needs_dot7_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}

define void @needs_dot8_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) #13 {
; GFX7-NOT:   define void @needs_dot8_insts(
; GFX8-NOT:   define void @needs_dot8_insts(
; GFX9-NOT:   define void @needs_dot8_insts(
; GFX10-NOT:  define void @needs_dot8_insts(
; GFX11:      define void @needs_dot8_insts(
  %add = add i64 %a, %b
  store i64 %add, ptr %out
  ret void
}

; IR: define void @caller(
define void @caller(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c) {
  ; GFX7: call void null(
  ; GFX8: call void @needs_dpp(
  ; GFX9: call void @needs_dpp(
  ; GFX10: call void @needs_dpp(
  ; GFX11: call void @needs_dpp(
  call void @needs_dpp(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void @needs_16bit_insts(
  ; GFX9: call void @needs_16bit_insts(
  ; GFX10: call void @needs_16bit_insts(
  ; GFX11: call void @needs_16bit_insts(
  call void @needs_16bit_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void @needs_gfx8_insts(
  ; GFX9: call void @needs_gfx8_insts(
  ; GFX10: call void @needs_gfx8_insts(
  ; GFX11: call void @needs_gfx8_insts(
  call void @needs_gfx8_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX9: call void @needs_gfx9_insts(
  ; GFX10: call void @needs_gfx9_insts(
  ; GFX111: call void @needs_gfx9_insts(c
  call void @needs_gfx9_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX9: call void null(
  ; GFX10: call void @needs_gfx10_insts(
  ; GFX111: call void @needs_gfx10_insts(
  call void @needs_gfx10_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX9: call void null(
  ; GFX10: call void null(
  ; GFX11: call void @needs_gfx11_insts(
  call void @needs_gfx11_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX9: call void @needs_dot1_insts(
  ; GFX10: call void @needs_dot1_insts(
  ; GFX11: call void null(
  call void @needs_dot1_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX9: call void @needs_dot2_insts(
  ; GFX10: call void @needs_dot2_insts(
  ; GFX11: call void null(
  call void @needs_dot2_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX906: call void null(
  ; GFX90A: call void @needs_dot3_insts(
  ; GFX10: call void null(
  ; GFX11: call void null(
  call void @needs_dot3_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX906: call void null(
  ; GFX90A: call void @needs_dot4_insts(
  ; GFX10: call void null(
  ; GFX11: call void null(
  call void @needs_dot4_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX906: call void null(
  ; GFX90A: call void @needs_dot5_insts(
  ; GFX10: call void @needs_dot5_insts(
  ; GFX11: call void @needs_dot5_insts(
  call void @needs_dot5_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX906: call void null(
  ; GFX90A: call void @needs_dot6_insts(
  ; GFX10: call void @needs_dot6_insts(
  ; GFX11: call void null(
  call void @needs_dot6_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX9: call void @needs_dot7_insts(
  ; GFX10: call void @needs_dot7_insts(
  ; GFX11: call void @needs_dot7_insts(
  call void @needs_dot7_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; GFX7: call void null(
  ; GFX8: call void null(
  ; GFX9: call void null(
  ; GFX10: call void null(
  ; GFX11: call void @needs_dot8_insts(
  call void @needs_dot8_insts(ptr %out, ptr %in, i64 %a, i64 %b, i64 %c)
  ; IR: ret void
  ret void
}

attributes #0 = { "target-features"="+dpp" }
attributes #1 = { "target-features"="+16-bit-insts" }
attributes #2 = { "target-features"="+gfx8-insts" }
attributes #3 = { "target-features"="+gfx9-insts" }
attributes #4 = { "target-features"="+gfx10-insts" }
attributes #5 = { "target-features"="+gfx11-insts" }
attributes #6 = { "target-features"="+dot1-insts" }
attributes #7 = { "target-features"="+dot2-insts" }
attributes #8 = { "target-features"="+dot3-insts" }
attributes #9 = { "target-features"="+dot4-insts" }
attributes #10 = { "target-features"="+dot5-insts" }
attributes #11 = { "target-features"="+dot6-insts" }
attributes #12 = { "target-features"="+dot7-insts" }
attributes #13 = { "target-features"="+dot8-insts" }
